#include "DonorList.h"

#include "iostream"
using namespace std;

DonorList::DonorList(const DonorList &another) {
    this->count = 0;
    this->first = nullptr;
    this->last = nullptr;
    Node *temp = another.first;
    while (temp != nullptr) {
        this->addDonor(
                temp->getDonor().getFirstName(),
                temp->getDonor().getLastName(),
                temp->getDonor().getMembershipNo(),
                temp->getDonor().getAmountDonated());
        temp = temp->getNext();
    }
}

DonorList &DonorList::operator=(const DonorList &another) {
    if (this == &another) {
        cerr << "The both objects are same." << endl;
    } else {
        if (this->isEmpty()) {
            this->copyCallingObjIsEmpty(another);
        } else {
            if (this->count == another.count) {
                this->copyObjectsSameLength(another);
            } else if (this->count < another.count) {
                this->copyCallingObjShorter(another);
            } else {
                this->copyCallingObjLonger(another);
            }
        }
    }
}

void DonorList::copyCallingObjIsEmpty(const DonorList& another) {
    if (this->isEmpty()) {
        Node *temp = another.first;
        while (temp != nullptr) {
            this->addDonor(
                temp->getDonor().getFirstName(),
                temp->getDonor().getLastName(),
                temp->getDonor().getMembershipNo(),
                temp->getDonor().getAmountDonated()
            );
            temp = temp->getNext();
        }
    }
}

void DonorList::copyObjectsSameLength(const DonorList& another) {
    if (this->count == another.count) {
        Node *tempThis = this->first;
        Node *tempAnother = another.first;
        while (tempAnother != nullptr) {
            tempThis->setDonor(DonorType{
                tempAnother->getDonor().getFirstName(),
                tempAnother->getDonor().getLastName(),
                tempAnother->getDonor().getMembershipNo(),
                tempAnother->getDonor().getAmountDonated()
            });
            tempThis = tempThis->getNext();
            tempAnother = tempAnother->getNext();
        }
    }
}

void DonorList::copyCallingObjLonger(const DonorList& another) {
    if (this->count >= another.count) {
        Node *tempThis = this->first;
        Node *tempAnother = another.first;
        while (tempAnother != nullptr) {
            tempThis->setDonor(DonorType{
                tempAnother->getDonor().getFirstName(),
                tempAnother->getDonor().getLastName(),
                tempAnother->getDonor().getMembershipNo(),
                tempAnother->getDonor().getAmountDonated()
            });
            if (tempAnother->getNext() != nullptr) {
                tempThis = tempThis->getNext();
                tempAnother = tempAnother->getNext();
            } else {
                break;
            }
        }
        while (tempThis->getNext() != nullptr) {
            Node *needDeleteNode = tempThis->getNext();
            tempThis->setNext(needDeleteNode->getNext());
            delete needDeleteNode;
            needDeleteNode = nullptr;
            this->count--;
        }
    }
}

void DonorList::copyCallingObjShorter(const DonorList& another) {
    if (this->count <= another.count) {
        Node *tempThis = this->first;
        Node *tempAnother = another.first;
        while (tempThis != nullptr) {
            tempThis->setDonor(DonorType{
                    tempAnother->getDonor().getFirstName(),
                    tempAnother->getDonor().getLastName(),
                    tempAnother->getDonor().getMembershipNo(),
                    tempAnother->getDonor().getAmountDonated()
            });
            tempThis = tempThis->getNext();
            tempAnother = tempAnother->getNext();
        }
        while (tempAnother != nullptr) {
            this->addDonor(
                    tempAnother->getDonor().getFirstName(),
                    tempAnother->getDonor().getLastName(),
                    tempAnother->getDonor().getMembershipNo(),
                    tempAnother->getDonor().getAmountDonated()
                    );
            this->count++;
            tempAnother = tempAnother->getNext();
        }
    }
}